package org.itsky.hystrix;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
import org.itsky.User;
import org.itsky.hystrix.service.HelloService;
import org.itsky.hystrix.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @Author sky
 * @Site cmtianxie163.com 2020/4/7 10:23
 */
@RestController
public class HelloController {
    @Autowired
    private HelloService helloService;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 调用注解方式的
     * @return
     */
    @GetMapping("/hello")
    public String hello(){
        return helloService.hello();
    }

    /**
     * 调用请求命令方式的 即继承类方式
     */
    @GetMapping("hello2")
    public void hello2() {
        HelloCommand helloCommand1 = new HelloCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("sky")), restTemplate);
        //方式一：直接执行 调用的是 run方法
        String s = helloCommand1.execute();
        System.out.println(s);

        //方式二： 先入队 后执行
        HelloCommand helloCommand2 = new HelloCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("sky")),restTemplate);

        try {
            Future<String> queue = helloCommand2.queue();
            String ss = queue.get();
            System.out.println(ss);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * 调用 注解方式的 请求异步调用
     */
    @GetMapping("hello3")
    public void hello3(){
        Future<String> stringFuture = helloService.hello2();
        try {
            String s = stringFuture.get();
            System.out.println(s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * service 的cacheresult注解配置后 缓存不会生效 一般我们使用缓存 都有一个缓存生命周期的概念
     * 这里也一样 我们需要初始化 HystrixRequsetContext,初始化完成后 缓存开始生效
     * HystrixRequestContext close之后，缓存失效。
     */
    @GetMapping("hello4")
    public void hello4(){
        HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
        String s = helloService.hello3("jin chengming");
        s = helloService.hello3("jin chengming");
        ctx.close();
    }

    @Autowired
    UserService userService;
    @GetMapping("hello5")
    public void hello5() throws ExecutionException, InterruptedException {
        HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
        UserCollapseCommand cmd1 = new UserCollapseCommand(userService, 18);
        UserCollapseCommand cmd2 = new UserCollapseCommand(userService, 19);
        UserCollapseCommand cmd3 = new UserCollapseCommand(userService, 20);
        UserCollapseCommand cmd4 = new UserCollapseCommand(userService, 21);
        UserCollapseCommand cmd5 = new UserCollapseCommand(userService, 22);
        Future<User> q1 = cmd1.queue();
        Future<User> q2 = cmd2.queue();
        Future<User> q3 = cmd3.queue();
        Future<User> q4 = cmd4.queue();

        User u1 = q1.get();
        User u2 = q2.get();
        User u3 = q3.get();
        User u4 = q4.get();

        System.out.println(u1);
        System.out.println(u2);
        System.out.println(u3);
        System.out.println(u4);
        Thread.sleep(2000);

        Future<User> q5 = cmd5.queue();
        User u5 = q5.get();
        System.out.println(u5);
        ctx.close();
    }

    @GetMapping("hello6")
    public void hello6() throws ExecutionException, InterruptedException {
        HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
        Future<User> q1 = userService.getUserById(99);
        System.out.println("---------------------");
        System.out.println(q1);
        System.out.println("---------------------");
        Future<User> q2 = userService.getUserById(98);
        Future<User> q3 = userService.getUserById(97);
        Future<User> q4 = userService.getUserById(96);
        User u1 = q1.get();
        User u2 = q2.get();
        User u3 = q3.get();
        User u4 = q4.get();
        System.out.println(u1);
        System.out.println(u2);
        System.out.println(u3);
        System.out.println(u4);
        Thread.sleep(2000);
        Future<User> q5 = userService.getUserById(95);
        User u5 = q5.get();
        System.out.println(u5);
        ctx.close();
    }
}
